"""
Explore command implementation.

Provides interactive manual exploration capabilities for function call trees
with code viewing and navigation features.
"""

import argparse
import asyncio
from typing import Dict, Any, List, Optional
from pathlib import Path

from ...core.error_handler import CodeMCPError, log_info
from ..base_command import CLICommand
from ..interactive.explorer import ManualExplorer


class ExploreCommand(CLICommand):
    """Command for interactive exploration of function call trees."""
    
    def add_parser(self, subparsers) -> argparse.ArgumentParser:
        """Add explore command parser."""
        parser = subparsers.add_parser(
            'explore',
            help='Interactively explore function call trees',
            description="""
Interactively explore function call trees with manual navigation,
code viewing, and weighted node selection capabilities.
            """.strip(),
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog="""
Examples:
  codemcp explore --file main.py --function main --mode manual
  codemcp explore --file src/app.cpp --function process_data
  codemcp explore --session my_exploration --resume
            """.strip()
        )
        
        # Input specification
        input_group = parser.add_argument_group('Input Options')
        input_group.add_argument(
            '--file', '-f',
            type=str,
            help='File to explore'
        )
        input_group.add_argument(
            '--function',
            type=str,
            help='Function name to start exploration from'
        )
        input_group.add_argument(
            '--language',
            choices=['python', 'cpp', 'fortran', 'typescript', 'latex', 'markdown', 'auto'],
            default='auto',
            help='Force specific language (default: auto-detect)'
        )
        
        # Exploration options
        explore_group = parser.add_argument_group('Exploration Options')
        explore_group.add_argument(
            '--mode',
            choices=['manual', 'guided'],
            default='manual',
            help='Exploration mode (default: manual)'
        )
        explore_group.add_argument(
            '--max-depth',
            type=int,
            default=20,
            help='Maximum exploration depth (default: 20)'
        )
        explore_group.add_argument(
            '--show-complexity',
            action='store_true',
            help='Show complexity scores for functions'
        )
        explore_group.add_argument(
            '--syntax-highlighting',
            action='store_true',
            default=True,
            help='Enable syntax highlighting for code viewing'
        )
        
        # Session management
        session_group = parser.add_argument_group('Session Options')
        session_group.add_argument(
            '--session',
            type=str,
            help='Session name for saving/loading exploration state'
        )
        session_group.add_argument(
            '--resume',
            action='store_true',
            help='Resume previous exploration session'
        )
        session_group.add_argument(
            '--auto-save',
            action='store_true',
            help='Automatically save exploration progress'
        )
        
        # Interface options
        interface_group = parser.add_argument_group('Interface Options')
        interface_group.add_argument(
            '--timeout',
            type=int,
            default=300,
            help='Timeout for user input in seconds (default: 300)'
        )
        interface_group.add_argument(
            '--max-selections',
            type=int,
            default=10,
            help='Maximum number of nodes in weighted selection (default: 10)'
        )
        
        return parser
    
    async def execute(self, args: argparse.Namespace) -> int:
        """Execute the explore command."""
        try:
            # Validate arguments
            await self._validate_arguments(args)
            
            # Show banner
            if not args.quiet:
                self.cli.print_banner()
                self.printer.print_info("Starting interactive exploration")
            
            # Initialize exploration session
            explorer = await self._initialize_explorer(args)
            
            # Start exploration
            result = await explorer.start_exploration()
            
            # Handle exploration result
            await self._handle_exploration_result(result, args)
            
            return 0
            
        except KeyboardInterrupt:
            self.printer.print_warning("\nExploration cancelled by user")
            return 1
        except CodeMCPError as e:
            self.printer.print_error(f"Exploration failed: {e.message}")
            return 1
        except Exception as e:
            self.printer.print_error(f"Unexpected error during exploration: {e}")
            return 1
    
    async def _validate_arguments(self, args: argparse.Namespace):
        """Validate command arguments."""
        if args.resume:
            if not args.session:
                raise CodeMCPError("Session name is required when using --resume")
        else:
            if not args.file:
                raise CodeMCPError("File path is required (use --file)")
            
            file_path = Path(args.file)
            if not file_path.exists():
                raise CodeMCPError(f"File does not exist: {args.file}")
            
            if not file_path.is_file():
                raise CodeMCPError(f"Path is not a file: {args.file}")
            
            if not args.function:
                raise CodeMCPError("Function name is required (use --function)")
        
        if args.max_depth < 1:
            raise CodeMCPError("Max depth must be at least 1")
        
        if args.timeout < 1:
            raise CodeMCPError("Timeout must be at least 1 second")
        
        if args.max_selections < 1:
            raise CodeMCPError("Max selections must be at least 1")
    
    async def _initialize_explorer(self, args: argparse.Namespace) -> ManualExplorer:
        """Initialize the manual explorer."""
        # Create explorer configuration
        config = {
            'max_depth': args.max_depth,
            'show_complexity': args.show_complexity,
            'syntax_highlighting': args.syntax_highlighting,
            'timeout_seconds': args.timeout,
            'max_selections': args.max_selections,
            'auto_save': args.auto_save,
            'session_name': args.session
        }
        
        # Initialize explorer
        explorer = ManualExplorer(self.config, config)
        
        if args.resume and args.session:
            # Resume existing session
            await explorer.load_session(args.session)
            self.printer.print_success(f"Resumed exploration session: {args.session}")
        else:
            # Start new exploration
            file_path = Path(args.file)
            
            # Determine language
            if args.language == 'auto':
                language = self.get_language_from_extension(file_path)
            else:
                language = args.language
            
            # Initialize new exploration
            await explorer.initialize_exploration(
                file_path=str(file_path),
                function_name=args.function,
                language=language
            )
            
            self.printer.print_success(f"Initialized exploration of {args.function} in {file_path.name}")
        
        return explorer
    
    async def _handle_exploration_result(self, result: Dict[str, Any], args: argparse.Namespace):
        """Handle the exploration result."""
        if result.get('cancelled'):
            self.printer.print_warning("Exploration was cancelled")
            return
        
        # Display exploration summary
        self.printer.print_header("Exploration Summary", level=1)
        
        summary_data = {
            'Session': result.get('session_name', 'unnamed'),
            'Duration': f"{result.get('duration', 0):.2f} seconds",
            'Nodes Visited': result.get('nodes_visited', 0),
            'Max Depth Reached': result.get('max_depth_reached', 0),
            'Manual Selections': result.get('manual_selections', 0),
            'Code Views': result.get('code_views', 0)
        }
        
        self.formatter.print_key_value_pairs(summary_data)
        
        # Display exploration path
        if result.get('exploration_path'):
            self.printer.print_header("Exploration Path", level=2)
            path = result['exploration_path']
            
            for i, node in enumerate(path):
                level = i
                is_last = i == len(path) - 1
                node_name = node.get('name', 'unknown')
                file_name = Path(node.get('file_path', '')).name
                line_num = node.get('line_number', 0)
                
                node_display = f"{node_name} ({file_name}:{line_num})"
                self.printer.print_call_tree_node(node_display, level, is_last)
        
        # Display interesting findings
        if result.get('findings'):
            self.printer.print_header("Key Findings", level=2)
            findings = result['findings']
            
            for finding in findings:
                finding_type = finding.get('type', 'info')
                message = finding.get('message', '')
                
                if finding_type == 'complexity':
                    self.printer.print_warning(f"High complexity: {message}")
                elif finding_type == 'cross_language':
                    self.printer.print_info(f"Cross-language call: {message}")
                elif finding_type == 'recursive':
                    self.printer.print_warning(f"Recursive call detected: {message}")
                else:
                    self.printer.print_info(message)
        
        # Save session if requested
        if args.auto_save or args.session:
            session_name = args.session or f"exploration_{int(result.get('start_time', 0))}"
            self.printer.print_success(f"Exploration session saved as: {session_name}")
        
        self.printer.print_success("Exploration completed successfully!")


class GuidedExplorer:
    """Guided exploration mode with AI assistance."""
    
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.printer = ColorPrinter()
    
    async def start_guided_exploration(self, file_path: str, function_name: str) -> Dict[str, Any]:
        """Start guided exploration with AI assistance."""
        # This would integrate with the AI/LLM system
        # For now, return a placeholder
        
        self.printer.print_info("Guided exploration mode (AI-assisted) is not yet implemented")
        self.printer.print_info("This would provide intelligent suggestions for exploration paths")
        
        return {
            'mode': 'guided',
            'status': 'not_implemented',
            'message': 'Guided exploration requires AI integration'
        }